﻿Imports System.Collections.Specialized
Imports Microsoft.VisualBasic.ControlChars
Imports System.Xml

Public Class frmTabTaxonomy

    Public Shared sTaxKeywords As StringCollection = New StringCollection()
    Public Shared citeTaxSys As Collection = New Collection() 'holds the main citation information for Taxonomic System
    Public Shared boolTaxSys As Collection = New Collection() 'holds Booleans indicating whether LWC is used
    Public Shared citeTaxSysLWC As Collection = New Collection() 'holds larger work citations
    Public Shared sTaxSysMods As StringCollection = New StringCollection() 'holds the Taxonomic System modifications
    Public Shared citeTaxIDRef As Collection = New Collection() 'holds the main citation information for Identification Reference
    Public Shared boolTaxIDRef As Collection = New Collection() 'holds Booleans indicating whether LWC is used
    Public Shared citeTaxIDRefLWC As Collection = New Collection() 'holds larger work citations
    Public Shared cntTaxID As Collection = New Collection() 'holds contact information for Identifier(s) -- optional
    Public Shared sVSpecimen As StringCollection = New StringCollection() 'holds the specimen info for vouchers
    Public Shared cntVouchers As Collection = New Collection() 'holds the contact info for voucher repository
    Public Shared TaxaClasses As Collection = New Collection() 'holds the taxonomic classification entries
    Public Shared xmlTaxonClass As XmlDocument = New XmlDocument() 'holds the Taxonomic Classification
    Public Shared sPdelim As String = "£"
    Public Shared sKdelim As String = CrLf
    Dim editNode As EditXML = New EditXML()

    Private Sub btnAddTaxKey_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddTaxKey.Click
        Dim sNewKey As String = ""
        Dim frmAddKeys As New frmTaxKey(sNewKey)
        frmAddKeys.ShowDialog()
        If (frmAddKeys.getUpdated() = True) Then 'add the keywords to collection
            sNewKey = frmAddKeys.getTaxKeys()
            sTaxKeywords.Add(sNewKey)
            sNewKey = Replace(sNewKey, sPdelim, ":  ") 'replace £ following thesaurus with colon and 2 spaces
            sNewKey = Replace(sNewKey, sKdelim, "; ") 'replace CRLF keyword spacer with semi-colon and space
            lboxTaxKey.Items.Add(sNewKey)
        End If
    End Sub

    Private Sub btnEditTaxKey_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEditTaxKey.Click
        Dim iToEdit As Integer = 0
        Dim sToEdit As String = ""
        Dim iCount As Integer = lboxTaxKey.Items.Count
        iToEdit = lboxTaxKey.SelectedIndex
        If (iCount = 1) Then iToEdit = 0
        If (iToEdit = -1) Then
            'no keyword list selected
            MessageBox.Show("No set of keywords selected for editing", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        sToEdit = sTaxKeywords(iToEdit)
        Dim frmKeyToEdit As New frmTaxKey(sToEdit)
        frmKeyToEdit.ShowDialog()
        If (frmKeyToEdit.getUpdated() = True) Then
            sToEdit = frmKeyToEdit.getTaxKeys() 'get the keyword pair
            sTaxKeywords.Insert(iToEdit, sToEdit) 'insert new pair into string collection
            sTaxKeywords.RemoveAt(iToEdit + 1)    'remove old pair from string collection
            sToEdit = Replace(sToEdit, sPdelim, ":  ") 'replace £ following thesaurus with colon and 2 spaces
            sToEdit = Replace(sToEdit, sKdelim, "; ") 'replace CRLF keyword spacer with semi-colon and space
            lboxTaxKey.Items.Insert(iToEdit, sToEdit)
            lboxTaxKey.Items.RemoveAt(iToEdit + 1)
        End If
        btnEditTaxKey.Enabled = False : btnDelTaxKey.Enabled = False
    End Sub

    Private Sub btnDelTaxKey_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelTaxKey.Click
        Dim iToEdit As Integer = 0
        iToEdit = lboxTaxKey.SelectedIndex
        If (iToEdit = -1) Then
            'no keyword list selected
            MessageBox.Show("No set of keywords selected for deletion", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If
        lboxTaxKey.Items.RemoveAt(iToEdit) 'zero based list
        sTaxKeywords.RemoveAt(iToEdit) 'zero-based string collection
        btnEditTaxKey.Enabled = False : btnDelTaxKey.Enabled = False
    End Sub

    Private Sub lboxTaxKey_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lboxTaxKey.SelectedIndexChanged
        If lboxTaxKey.SelectedItems.Count() > 0 Then btnEditTaxKey.Enabled = True : btnDelTaxKey.Enabled = True Else btnEditTaxKey.Enabled = False : btnDelTaxKey.Enabled = False
    End Sub

    Private Sub btnAddTaxRank_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddTaxRank.Click, Button1.Click
        'create new node and either set as top node or attach as child to selected node, update collection and listbox
        Dim iTaxaCount As Integer = TaxaClasses.Count
        Dim iSelIndex As Integer = lboxLinneaus.SelectedIndex
        If (iSelIndex = -1 And iTaxaCount > 0) Then
            MessageBox.Show("No parent node selected for child to be added to.", "Taxonomic selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        Dim xmlNList As XmlNodeList
        Dim xmlTaxaNode As XmlNode
        Dim sTaxaInfo As String = ""
        Dim oNewTaxa As New TaxonClass
        Dim oTaxaNode As TaxonClass 'generic taxon node
        Dim frmNewTaxRank As New frmTaxonClass(oNewTaxa)
        frmNewTaxRank.ShowDialog()
        If (frmNewTaxRank.getUpdated() = True) Then
            'add newly described taxonomic classification node
            oNewTaxa = frmNewTaxRank.getTaxRank()
            xmlTaxaNode = xmlNewTaxonClassNode(oNewTaxa) 'creates the new XML node
            If (iSelIndex = -1) Then
                xmlTaxonClass.AppendChild(xmlTaxaNode) 'put node into empty XML document
            Else
                'attach to selected node
                xmlNList = xmlTaxonClass.GetElementsByTagName("taxoncl")
                xmlNList.Item(iSelIndex).AppendChild(xmlTaxaNode)
            End If

            ' 1. re-build the TaxaClasses collection
            TaxaClasses = New Collection
            xmlNList = xmlTaxonClass.SelectNodes("/taxoncl")
            If (xmlNList.Count > 0) Then
                sTaxaInfo = xmlNList(0).OuterXml
                openIDtaxclass(sTaxaInfo)
            End If

            ' 2. re-create the display
            lboxLinneausBuild() 'rebuild listbox from the updated TaxaClasses collection
        End If
        validateAdd()
    End Sub
    Private Sub openIDtaxclass(ByVal sTaxClass As String)
        Dim xmlTaxClassDoc As New XmlDocument
        Dim xmlNList As XmlNodeList
        Dim s1 As String = ""
        Dim sIDinfo As String = ""
        Dim iCount As Integer = 0
        Dim iLoop As Integer = 0
        Dim iLevel As Integer = 0
        Dim oNewTaxa As New TaxonClass

        xmlTaxClassDoc.LoadXml(sTaxClass) 'node exists, fill local DOM
        oNewTaxa = New TaxonClass

        xmlNList = xmlTaxClassDoc.SelectNodes("/taxoncl/taxonrn")
        If (xmlNList.Count > 0) Then 'get rank name
            oNewTaxa.RankName = xmlNList(0).InnerText.Trim
        End If
        xmlNList = xmlTaxClassDoc.SelectNodes("/taxoncl/taxonrv")
        If (xmlNList.Count > 0) Then 'get rank value
            oNewTaxa.RankValue = xmlNList(0).InnerText.Trim
        End If
        xmlNList = xmlTaxClassDoc.SelectNodes("/taxoncl/common")
        iCount = xmlNList.Count - 1
        s1 = ""
        For iLoop = 0 To iCount
            'process common names
            s1 = xmlNList(iLoop).InnerText.Trim & sKdelim
        Next
        oNewTaxa.CommonName = s1

        'set base level to zero
        iLevel = 0
        oNewTaxa.Level = iLevel

        'process additional taxonomic classification nodes
        xmlNList = xmlTaxClassDoc.SelectNodes("/taxoncl/taxoncl")
        iCount = xmlNList.Count
        oNewTaxa.Nchildren = iCount
        TaxaClasses.Add(oNewTaxa) 'add node to main collection
        iLevel += 1
        For iLoop = 0 To iCount - 1
            sIDinfo = xmlNList(iLoop).OuterXml
            openIDtaxon(sIDinfo, iLevel)
        Next

    End Sub
    Private Sub openIDtaxon(ByVal sTaxon As String, ByVal iLevel As Integer)
        'sTaxon contains an XML string, iLevel is the current level
        Dim xmlTaxClassDoc As New XmlDocument
        Dim xmlNList As XmlNodeList
        Dim xmlPlist As XmlNodeList
        Dim s1 As String = ""
        Dim sIDinfo As String = ""
        Dim iCount As Integer = 0
        Dim iLoop As Integer = 0
        Dim oNewTaxa As New TaxonClass

        xmlTaxClassDoc.LoadXml(sTaxon) 'node exists, fill local DOM
        oNewTaxa = New TaxonClass

        xmlNList = xmlTaxClassDoc.SelectNodes("/taxoncl/taxonrn")
        If (xmlNList.Count > 0) Then 'get rank name
            oNewTaxa.RankName = xmlNList(0).InnerText.Trim
        End If
        xmlNList = xmlTaxClassDoc.SelectNodes("/taxoncl/taxonrv")
        If (xmlNList.Count > 0) Then 'get rank value
            oNewTaxa.RankValue = xmlNList(0).InnerText.Trim
        End If
        xmlNList = xmlTaxClassDoc.SelectNodes("/taxoncl/common")
        iCount = xmlNList.Count - 1
        s1 = ""
        For iLoop = 0 To iCount
            'process common names
            s1 = s1 & xmlNList(iLoop).InnerText.Trim & sKdelim
        Next
        oNewTaxa.CommonName = s1

        'set current node's level
        oNewTaxa.Level = iLevel

        'process additional taxonomic classification nodes
        xmlNList = xmlTaxClassDoc.SelectNodes("/taxoncl/taxoncl")
        iCount = xmlNList.Count
        oNewTaxa.Nchildren = iCount
        TaxaClasses.Add(oNewTaxa) 'add node to main collection
        iLevel += 1
        For iLoop = 0 To iCount - 1
            sIDinfo = xmlNList(iLoop).OuterXml
            openIDtaxon(sIDinfo, iLevel)
        Next
    End Sub

    Private Sub btnEditTaxRank_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEditTaxRank.Click, Button2.Click
        'simple edit of existing node with re-insertion, update listbox
        Dim sIndent As String = "   "
        Dim iLoop As Integer = 0
        Dim iToStart As Integer = 0
        Dim iToEnd As Integer = 0
        Dim sTemp As String = ""
        Dim xmlNList As XmlNodeList
        Dim xmlChildList As XmlNodeList
        Dim oTaxaToEdit As TaxonClass
        Dim iCommonName As Integer = 0
        Dim s1 As String = ""
        Dim sGenArray() As String
        Dim xmlTempNode As XmlNode 'transient node for <common> elements
        Dim xmlTaxaFrag As XmlDocumentFragment 'container for <common> elements
        Dim iCount As Integer = lboxLinneaus.Items.Count
        Dim iToEdit As Integer = lboxLinneaus.SelectedIndex '0-based listbox index
        If (iCount = 1) Then iToEdit = 0
        If (iToEdit = -1) Then
            MessageBox.Show("No taxonomic node selected for editing.", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        oTaxaToEdit = CType(TaxaClasses(iToEdit + 1), TaxonClass) '1-based collection index
        Dim frmEditTaxRank As New frmTaxonClass(oTaxaToEdit)
        frmEditTaxRank.ShowDialog()
        If (frmEditTaxRank.getUpdated() = True) Then
            oTaxaToEdit = frmEditTaxRank.getTaxRank()

            'update the taxonomic classification collection
            TaxaClasses.Add(oTaxaToEdit, , iToEdit + 1) 'inserts the edited node
            TaxaClasses.Remove(iToEdit + 2) 'removes the old node

            'update the XML taxonomic classification document
            xmlNList = xmlTaxonClass.GetElementsByTagName("taxoncl")
            'xmlNList.Item(iToEdit).ParentNode.ReplaceChild(xmlTaxaNode, xmlNList.Item(iToEdit)) 'takes out too much -- all descendant <taxoncl> nodes
            'xmlChildList = xmlNList.Item(iToEdit).ChildNodes
            'update the Taxon Rank Name
            xmlNList.Item(iToEdit).SelectSingleNode("taxonrn").InnerXml = oTaxaToEdit.RankName
            'update the Taxon Rank Value
            xmlNList.Item(iToEdit).SelectSingleNode("taxonrv").InnerXml = oTaxaToEdit.RankValue
            'remove existing common names
            xmlChildList = xmlNList.Item(iToEdit).SelectNodes("common")
            iToEnd = xmlChildList.Count
            For iLoop = 1 To iToEnd
                xmlNList.Item(iToEdit).RemoveChild(xmlNList.Item(iToEdit).SelectSingleNode("common"))
            Next
            'create fragment containing common name nodes and insert
            iCommonName = 0
            xmlTaxaFrag = xmlTaxonClass.CreateDocumentFragment
            If (oTaxaToEdit.CommonName <> "") Then
                sGenArray = Split(oTaxaToEdit.CommonName, sKdelim)
                iToEnd = sGenArray.GetUpperBound(0)
                For iToStart = 0 To iToEnd
                    s1 = sGenArray(iToStart).Trim
                    If (s1 <> "") Then
                        xmlTempNode = xmlTaxonClass.CreateElement("common")
                        xmlTempNode.InnerText = s1
                        xmlTaxaFrag.AppendChild(xmlTempNode)
                        iCommonName += 1 'increment counter
                    End If
                Next
                If (iCommonName > 0) Then
                    xmlNList.Item(iToEdit).InsertAfter(xmlTaxaFrag, xmlNList.Item(iToEdit).SelectSingleNode("taxonrv"))
                End If
            End If

            'update the list box
            iToEnd = oTaxaToEdit.Level
            For iLoop = 1 To iToEnd
                sTemp = sTemp & sIndent 'indent the node
            Next
            sTemp = sTemp & "rank: " & oTaxaToEdit.RankName & "  value: " & oTaxaToEdit.RankValue
            lboxLinneaus.Items.Insert(iToEdit, sTemp) 'insert edited taxonomic node
            lboxLinneaus.Items.RemoveAt(iToEdit + 1) 'remove old node
        End If
        btnEditTaxRank.Enabled = False : btnDelTaxRank.Enabled = False
        validateAdd()
    End Sub

    Private Function xmlNewTaxonClassNode(ByVal oCurTaxa As TaxonClass) As XmlNode
        Dim iToStart As Integer = 0
        Dim iToEnd As Integer = 0
        Dim s1 As String = ""
        Dim sGenArray() As String
        Dim xmlTempNode As XmlNode 'transient node for pieces of xmlNewTaxonClassNode

        'process taxonomic classification
        xmlNewTaxonClassNode = xmlTaxonClass.CreateElement("taxoncl") 'set the root element
        xmlTempNode = xmlTaxonClass.CreateElement("taxonrn") 'set the root rank name
        xmlTempNode.InnerText = oCurTaxa.RankName
        xmlNewTaxonClassNode.AppendChild(xmlTempNode)
        xmlTempNode = xmlTaxonClass.CreateElement("taxonrv") 'set the root rank value
        xmlTempNode.InnerText = oCurTaxa.RankValue
        xmlNewTaxonClassNode.AppendChild(xmlTempNode)
        If (oCurTaxa.CommonName <> "") Then
            sGenArray = Split(oCurTaxa.CommonName, sKdelim)
            iToEnd = sGenArray.GetUpperBound(0)
            For iToStart = 0 To iToEnd
                s1 = sGenArray(iToStart).Trim
                If (s1 <> "") Then
                    xmlTempNode = xmlTaxonClass.CreateElement("common")
                    xmlTempNode.InnerText = s1
                    xmlNewTaxonClassNode.AppendChild(xmlTempNode)
                End If
            Next
        End If
    End Function

    Private Sub btnDelTaxRank_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelTaxRank.Click, Button3.Click
        'need to delete selected taxonomic node and its children, if any; decrement parent node child count, update listbox
        Dim xmlNList As XmlNodeList
        Dim iToDelete As Integer = lboxLinneaus.SelectedIndex
        Dim sTaxaInfo As String = ""
        Dim oTaxaInfo As New TaxonClass
        Dim xmlNodeDel As XmlNode

        'process error of no node selected for deletion
        If (iToDelete = -1) Then
            MessageBox.Show("No taxonomic node selected for deletion", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        'process deletion of root taxonomic classification node
        If (iToDelete = 0) Then
            xmlTaxonClass = New XmlDocument
            TaxaClasses = New Collection
            lboxLinneaus.Items.Clear()
            Return
        End If

        'process deletion of interior taxonomic classification node
        xmlNList = xmlTaxonClass.GetElementsByTagName("taxoncl")
        xmlNList.Item(iToDelete).RemoveAll()

        'remove empty taxoncl node
        xmlNList.Item(iToDelete).ParentNode.RemoveChild(xmlNList.Item(iToDelete))

        ' 1. re-build the TaxaClasses collection
        TaxaClasses = New Collection
        xmlNList = xmlTaxonClass.SelectNodes("/taxoncl")
        If (xmlNList.Count > 0) Then
            sTaxaInfo = xmlNList(0).OuterXml
            openIDtaxclass(sTaxaInfo)
        End If

        ' 2. re-create the display
        lboxLinneausBuild()

        btnEditTaxRank.Enabled = False : btnDelTaxRank.Enabled = False
        validateAdd()
    End Sub

    Private Sub btnExpTaxa_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExpTaxa.Click, Button5.Click
        'exports XML taxonomic description to file: selected node, all children, and parental lineage
        Dim sTemp As String = ""
        Dim xmlNList As XmlNodeList
        Dim xmlChildList As XmlNodeList 'works with <common> elements
        Dim sOutputXML As String = ""
        Dim xmlExportDoc As XmlDocument
        Dim xmlExportNode As XmlNode 'container for taxonomic tree to be exported
        Dim xmlParentNode As XmlNode 'placeholder for navigating tree
        Dim xmlParentTree As XmlNode 'container for parent node content
        Dim xmlTempNode As XmlNode 'transient node
        Dim xmlTempNode2 As XmlNode 'another transient node
        Dim xmlTempNode3 As XmlNode 'another transient node
        Dim bParent As Boolean = True 'parent node is present
        Dim sRankName As String = ""
        Dim sRankValue As String = ""
        Dim sTestName As String = ""
        Dim sTestValue As String = ""
        Dim iToStart As Integer = 0
        Dim iToEnd As Integer = 0
        Dim iCount As Integer = lboxLinneaus.Items.Count
        Dim iToEdit As Integer = lboxLinneaus.SelectedIndex '0-based listbox index

        If (iCount = 0) Then 'no nodes defined yet
            sTemp = "No taxonomic nodes are currently defined." & vbCrLf & "Export to file not available."
            MessageBox.Show(sTemp, "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If
        If (iToEdit = -1) Then 'nodes exist but none are selected
            MessageBox.Show("No taxonomic node selected for export.", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        If (iToEdit = 0) Then 'export complete tree
            SaveTaxonDialog.ShowDialog()
            sOutputXML = SaveTaxonDialog.FileName
            If (sOutputXML <> "") Then
                xmlTaxonClass.Save(sOutputXML) 'write the XML node to the specified file
            Else
                sTemp = "No file name given. Save terminated!"
                MessageBox.Show(sTemp, "File save error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If
            Return
        End If

        'selected node is in tree interior
        xmlNList = xmlTaxonClass.GetElementsByTagName("taxoncl")
        'locate the selected node and place it and descendants into output container
        xmlTempNode = xmlNList.Item(iToEdit) 'sets the context node
        xmlExportNode = xmlTempNode.CloneNode(True) 'put context node and all children into export container

        'add parent nodes
        sRankName = xmlTaxonClass.DocumentElement.SelectSingleNode("taxonrn").InnerXml
        sRankValue = xmlTaxonClass.DocumentElement.SelectSingleNode("taxonrv").InnerXml
        While bParent = True
            xmlParentNode = xmlTempNode.ParentNode
            xmlParentTree = xmlTempNode.ParentNode.CloneNode(True) 'get parent node (includes all children)
            sTemp = xmlParentTree.SelectSingleNode("taxonrn").InnerXml
            If (sTemp = "Empire") Then
                bParent = False 'reached the top and do not include "Empire"
            Else
                'add parent to export node tree
                xmlTempNode2 = xmlTaxonClass.CreateElement("taxoncl")
                xmlTempNode3 = xmlParentTree.SelectSingleNode("taxonrn").Clone
                xmlTempNode2.AppendChild(xmlTempNode3) 'add Rank Name
                xmlTempNode3 = xmlParentTree.SelectSingleNode("taxonrv").Clone
                xmlTempNode2.AppendChild(xmlTempNode3) 'add Rank Value
                xmlChildList = xmlParentTree.SelectNodes("common") 'retrieve common names, if any
                iToEnd = xmlChildList.Count
                If (iToEnd > 0) Then 'add common names to output tree
                    For iToStart = 0 To iToEnd - 1
                        xmlTempNode3 = xmlChildList(iToStart).Clone
                        xmlTempNode2.AppendChild(xmlTempNode3)
                    Next
                End If

                xmlTempNode2.AppendChild(xmlExportNode) 'add rest of descendants
                xmlExportNode = xmlTempNode2.CloneNode(True)

                'test for root position and update nodes
                sTestName = xmlParentTree.SelectSingleNode("taxonrn").InnerXml
                sTestValue = xmlParentTree.SelectSingleNode("taxonrv").InnerXml
                If (sTestName = sRankName And sTestValue = sRankValue) Then bParent = False

                'update context node
                xmlTempNode = xmlParentNode 'update position in tree
            End If
        End While

        xmlExportDoc = New XmlDocument
        sTemp = xmlExportNode.OuterXml
        xmlExportDoc.LoadXml(sTemp)
        SaveTaxonDialog.ShowDialog()
        sOutputXML = SaveTaxonDialog.FileName
        If (sOutputXML <> "") Then
            xmlExportDoc.Save(sOutputXML) 'write the XML node to the specified file
            SaveTaxonDialog.Dispose()
        Else
            sTemp = "No file name given. Save terminated!"
            MessageBox.Show(sTemp, "File save error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End If

    End Sub

    Private Sub btnImpTaxa_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnImpTaxa.Click, Button4.Click
        'imports XML taxonomic description from file and attaches to taxonomic classification at selected node
        'will bring in all child nodes descending from matching selected node

        Dim xmlImportTaxDOM As XmlDocument
        Dim sError As String = ""
        Dim xmlNList As XmlNodeList
        Dim xmlNList2 As XmlNodeList
        Dim iTaxoncl As Integer = 0
        Dim iTaxonrn As Integer = 0
        Dim iTaxonrv As Integer = 0
        Dim iTaxonIndex As Integer = 0
        Dim iTaxonCount As Integer = 0
        Dim sTaxonrn As String = ""
        Dim sTaxonrv As String = ""
        Dim xmlTaxaNode As XmlNode
        Dim xmlTaxaFrag As XmlDocumentFragment
        Dim sTaxaInfo As String = ""
        Dim sTaxaClass As String = ""
        Dim sTaxaClass2 As String = ""
        Dim sTaxaImportClass As String = ""
        Dim oTaxonClass As New TaxonClass
        Dim iSelIndex As Integer = 0
        Dim bComplete As Boolean = False
        Dim bTaxonRN As Boolean = False
        Dim bTaxonRV As Boolean = False
        Dim iTaxaCount As Integer = lboxLinneaus.Items.Count

        xmlImportTaxDOM = New XmlDocument 'initialize the DOM
        iSelIndex = lboxLinneaus.SelectedIndex

        'if there are multiple nodes present, make sure one is chosen for processing
        If (iSelIndex = -1 And iTaxaCount > 1) Then
            sError = "No taxon node chosen for appending file"
            MessageBox.Show(sError, "Importing Taxonomic Classification", MessageBoxButtons.OK)
            Return
        End If

        'get the file to import and load to DOM
        If OpenTaxonFileDialog.ShowDialog() = DialogResult.OK Then
            Try
                'load XML into Document Object Model (DOM)
                xmlImportTaxDOM.Load(OpenTaxonFileDialog.FileName)
            Catch ex As Exception
                sError = "Error loading taxonomic classification XML from specified file"
                MessageBox.Show(ex.Message, sError, MessageBoxButtons.OK, MessageBoxIcon.Error)
                OpenTaxonFileDialog.Dispose()
                Return
            End Try
            OpenTaxonFileDialog.Dispose()
        Else
            Return
        End If

        'file succesfully opened and XML loaded into xmlImportTaxDOM

        'check file for minimal taxonomic classification structure
        xmlNList = xmlImportTaxDOM.GetElementsByTagName("taxoncl")
        iTaxoncl = xmlNList.Count
        xmlNList = xmlImportTaxDOM.GetElementsByTagName("taxonrn")
        iTaxonrn = xmlNList.Count
        xmlNList = xmlImportTaxDOM.GetElementsByTagName("taxonrv")
        iTaxonrv = xmlNList.Count
        If (iTaxoncl = 0 Or iTaxonrn = 0 Or iTaxonrv = 0) Then
            sError = "XML structure is not consistent with a taxonomic classification"
            MessageBox.Show(sError, "Import error", MessageBoxButtons.OK)
            Return
        End If

        'determine whether any Taxonomic Classification already exists
        'CASE 1: if none exists, then make imported classification the classification; update
        'CASE 2: if only "Empire" exists, then add imported classification to "Empire"; update
        'CASE 3: many nodes, but selected node is "Empire", then add imported classification to "Empire"; update
        'CASE 4: if nodes other than "Empire" exist, then attempt node matching

        bComplete = False 'import not complete yet

        'Handle CASE 1
        If (iTaxaCount = 0) Then
            'make imported classification the classification
            sTaxaClass = xmlImportTaxDOM.DocumentElement.OuterXml
            xmlTaxonClass.LoadXml(sTaxaClass)
            bComplete = True
        End If

        'Handle CASE 2
        If (iTaxaCount = 1) Then
            oTaxonClass = CType(TaxaClasses.Item(1), TaxonClass)
            sTaxaInfo = oTaxonClass.RankName
            If (sTaxaInfo = "Empire") Then
                sTaxaImportClass = xmlImportTaxDOM.DocumentElement.SelectSingleNode("taxonrn").InnerXml
                If (sTaxaImportClass = "Empire") Then
                    'make imported classification the classification
                    sTaxaClass = xmlImportTaxDOM.DocumentElement.OuterXml
                    xmlTaxonClass.LoadXml(sTaxaClass)
                    bComplete = True
                Else
                    'append file classification to top node
                    sTaxaClass = xmlImportTaxDOM.DocumentElement.OuterXml
                    xmlTaxaFrag = xmlTaxonClass.CreateDocumentFragment
                    xmlTaxaFrag.InnerXml = sTaxaClass
                    xmlTaxonClass.DocumentElement.AppendChild(xmlTaxaFrag)
                    bComplete = True
                End If
            Else
                iSelIndex = 0 'if single existing node isn't "Empire" then setup for node matching
            End If

        End If

        'Handle CASE 3
        If (iTaxaCount > 1 And iSelIndex = 0) Then  'multiple nodes; top node selected
            oTaxonClass = CType(TaxaClasses.Item(1), TaxonClass)
            sTaxaInfo = oTaxonClass.RankName
            If (sTaxaInfo = "Empire") Then
                'append file classification to top node
                sTaxaClass = xmlImportTaxDOM.DocumentElement.OuterXml
                xmlTaxaFrag = xmlTaxonClass.CreateDocumentFragment
                xmlTaxaFrag.InnerXml = sTaxaClass
                xmlTaxonClass.DocumentElement.AppendChild(xmlTaxaFrag)
                bComplete = True
            End If
        Else
        End If

        'Handle CASE 4
        If (bComplete = False) Then
            'working with a node selected for appending
            'get the Rank Name and Rank Value of selected node (for matching in the imported file)
            oTaxonClass = CType(TaxaClasses.Item(iSelIndex + 1), TaxonClass)
            sTaxonrn = oTaxonClass.RankName
            sTaxonrv = oTaxonClass.RankValue
            xmlNList = xmlImportTaxDOM.GetElementsByTagName("taxoncl")
            iTaxoncl = xmlNList.Count - 1
            sTaxaClass = "taxonrn[text() = '" & sTaxonrn & "']"   'sets XPath params for taxonrn nodes
            sTaxaClass2 = "taxonrv[text() = '" & sTaxonrv & "']"  'sets XPath params for taxonrv nodes
            bTaxonRN = False
            bTaxonRV = False
            iTaxaCount = 0
            For iTaxonrn = 0 To iTaxoncl
                xmlNList2 = xmlNList.Item(iTaxonrn).SelectNodes(sTaxaClass)
                If (xmlNList2.Count > 0) Then 'found a taxonrn match at iTaxonrn
                    xmlNList2 = xmlNList.Item(iTaxonrn).SelectNodes(sTaxaClass2)
                    If (xmlNList2.Count > 0) Then  'found a taxonrv match at iTaxonrn
                        iTaxonIndex = iTaxonrn
                        bTaxonRV = True
                        iTaxaCount = iTaxaCount + 1
                    End If
                End If
            Next
            If (iTaxaCount = 0) Then
                sError = "No matching node found in the import file" & vbCrLf & "No import performed"
                MessageBox.Show(sError, "Import Taxonomic Classification error", MessageBoxButtons.OK)
                Return
            End If
            If (iTaxaCount > 1) Then
                sError = "More than one matching node in the import file" & vbCrLf & "Cannot determine which to append"
                sError = sError & vbCrLf & "No import performed"
                MessageBox.Show(sError, "Import Taxonomic Classification error", MessageBoxButtons.OK)
                Return
            End If
            xmlTaxaNode = xmlNList.Item(iTaxonIndex).CloneNode(True)
            sTaxaInfo = xmlTaxaNode.OuterXml
            xmlTaxaNode.RemoveChild(xmlTaxaNode.SelectSingleNode("taxonrn")) 'eliminates duplicate taxonrn
            xmlTaxaNode.RemoveChild(xmlTaxaNode.SelectSingleNode("taxonrv")) 'eliminates duplicate taxonrv
            xmlNList = xmlTaxaNode.SelectNodes("/common")                    'determine whether any "common" elements
            iTaxoncl = xmlNList.Count                                        '  are present; if so, delete
            For iTaxonrn = 1 To iTaxoncl
                xmlTaxaNode.RemoveChild(xmlTaxaNode.SelectSingleNode("common"))
            Next
            sTaxaInfo = xmlTaxaNode.InnerXml                                'get XML to be imported
            xmlTaxaFrag = xmlTaxonClass.CreateDocumentFragment
            xmlTaxaFrag.InnerXml = sTaxaInfo                                'put import XML into DocFrag of right type
            xmlNList = xmlTaxonClass.GetElementsByTagName("taxoncl")        'get all existing taxoncl elements
            xmlNList(iSelIndex).AppendChild(xmlTaxaFrag)                    'append import XML to selected existing node
            bComplete = True
        End If

        If (bComplete = True) Then
            'Update interface
            ' 1. re-build the TaxaClasses collection
            TaxaClasses = New Collection
            xmlNList = xmlTaxonClass.SelectNodes("/taxoncl")
            If (xmlNList.Count > 0) Then
                sTaxaInfo = xmlNList(0).OuterXml
                openIDtaxclass(sTaxaInfo)
            End If

            ' 2. re-create the display
            lboxLinneausBuild() 'rebuild listbox from the updated TaxaClasses collection
        Else
            sError = "Serious error resulting in no update"
            sError = sError & vbCrLf & "Record what you did and send information to Dave"
            sError = sError & vbCrLf & "(Contact info under Help)"
            MessageBox.Show(sError, "Taxonomic Import Error", MessageBoxButtons.OK)
        End If

    End Sub

    Public Sub lboxLinneausBuild()
        Dim sIndent As String = "   "
        Dim iLoop As Integer = 0
        Dim iLoop2 As Integer = 0
        Dim iNodes As Integer = 0
        Dim iToEnd As Integer = 0
        Dim sTemp As String = ""
        Dim oTaxaInfo As TaxonClass

        lboxLinneaus.Items.Clear() 'clear the existing list structure
        iNodes = TaxaClasses.Count 'get number of taxa nodes to process
        For iLoop = 1 To iNodes
            sTemp = ""
            oTaxaInfo = CType(TaxaClasses(iLoop), TaxonClass) 'get taxa node
            iToEnd = oTaxaInfo.Level
            For iLoop2 = 1 To iToEnd
                sTemp = sTemp & sIndent 'indent the node
            Next
            sTemp = sTemp & "rank: " & oTaxaInfo.RankName & "  value: " & oTaxaInfo.RankValue
            lboxLinneaus.Items.Add(sTemp) 'add the taxonomic node
        Next
    End Sub

    Private Sub lboxLinneaus_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lboxLinneaus.SelectedIndexChanged
        If lboxLinneaus.SelectedItems.Count() > 0 Then btnEditTaxRank.Enabled = True : btnDelTaxRank.Enabled = True Else btnEditTaxRank.Enabled = False : btnDelTaxRank.Enabled = False
        validateAdd()
    End Sub
    Private Sub validateAdd()
        If lboxLinneaus.Items.Count() = 0 Then
            btnAddTaxRank.Enabled = True
        ElseIf lboxLinneaus.SelectedItems.Count() = 0 Then
            btnAddTaxRank.Enabled = False
        Else
            btnAddTaxRank.Enabled = True
        End If
    End Sub
    Private Sub btnAddTaxSys_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddTaxSys.Click
        Dim sTemp As String = ""
        Dim oNewCite As New CiteInfo 'taxonomic system classification system citation
        Dim bNewCiteLWC As Boolean = False
        Dim oNewCiteLWC As New CiteInfo 'taxonomic system classification system larger work citation
        Dim sSysMod As String = "" 'taxonomic system modifications
        Dim frmAddTaxSys As New frmTaxSysClass(oNewCite, bNewCiteLWC, oNewCiteLWC, sSysMod)

        frmAddTaxSys.ShowDialog()
        If (frmAddTaxSys.getUpdated() = True) Then 'create the new taxonomic system entry
            oNewCite = frmAddTaxSys.getCite()
            bNewCiteLWC = frmAddTaxSys.getbCiteLWC()
            oNewCiteLWC = frmAddTaxSys.getCiteLWC()
            sSysMod = frmAddTaxSys.getMods()
            citeTaxSys.Add(oNewCite)
            boolTaxSys.Add(bNewCiteLWC)
            citeTaxSysLWC.Add(oNewCiteLWC)
            sTaxSysMods.Add(sSysMod)
            sTemp = "cite: " & oNewCite.Author & " — " & oNewCite.Title
            lboxTaxSys.Items.Add(sTemp)
            sTemp = "  modifications: " & Microsoft.VisualBasic.Left(sSysMod, 50)
            lboxTaxSys.Items.Add(sTemp)
        End If

    End Sub

    Private Sub btnEditTaxSys_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEditTaxSys.Click
        Dim sTemp As String = ""
        Dim iCount As Integer = lboxTaxSys.Items.Count
        Dim iToEdit As Integer = lboxTaxSys.SelectedIndex
        If (iCount = 1) Then iToEdit = 0
        If (iToEdit = -1) Then
            MessageBox.Show("No entry selected for editing", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        'if valid line selected, set up to edit the appropriate entries
        iToEdit = CInt(CDbl(iToEdit) / 2.0 - 0.05) 're-scales; uses zero-based index
        Dim oNewCite As CiteInfo = CType(citeTaxSys(iToEdit + 1), CiteInfo) 'taxonomic system classification system citation
        Dim bNewCiteLWC As Boolean = CType(boolTaxSys(iToEdit + 1), Boolean)
        Dim oNewCiteLWC As CiteInfo = CType(citeTaxSysLWC(iToEdit + 1), CiteInfo) 'associated larger work citation
        Dim sSysMod As String = sTaxSysMods(iToEdit) 'taxonomic system modifications; zero-based index

        Dim frmEditTaxSys As New frmTaxSysClass(oNewCite, bNewCiteLWC, oNewCiteLWC, sSysMod)
        frmEditTaxSys.ShowDialog()
        If (frmEditTaxSys.getUpdated() = True) Then 'create the new taxonomic system entry
            oNewCite = frmEditTaxSys.getCite()
            bNewCiteLWC = frmEditTaxSys.getbCiteLWC()
            oNewCiteLWC = frmEditTaxSys.getCiteLWC()
            sSysMod = frmEditTaxSys.getMods()
            citeTaxSys.Add(oNewCite, , iToEdit + 1)
            boolTaxSys.Add(bNewCiteLWC, , iToEdit + 1)
            citeTaxSysLWC.Add(oNewCiteLWC, , iToEdit + 1)
            sTaxSysMods.Insert(iToEdit, sSysMod)
            'delete old taxonomic system entry
            citeTaxSys.Remove(iToEdit + 2)
            boolTaxSys.Remove(iToEdit + 2)
            citeTaxSysLWC.Remove(iToEdit + 2)
            sTaxSysMods.RemoveAt(iToEdit + 1)

            iToEdit *= 2 're-expand the index for working with list box
            sTemp = "cite: " & oNewCite.Author & " — " & oNewCite.Title
            lboxTaxSys.Items.Insert(iToEdit, sTemp)
            sTemp = "  modifications: " & Microsoft.VisualBasic.Left(sSysMod, 50)
            lboxTaxSys.Items.Insert(iToEdit + 1, sTemp)
            lboxTaxSys.Items.RemoveAt(iToEdit + 2) 'removes old citation
            lboxTaxSys.Items.RemoveAt(iToEdit + 2) 'removes old modifications
        End If
        btnEditTaxSys.Enabled = False : btnDelTaxSys.Enabled = False
    End Sub

    Private Sub btnDelTaxSys_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelTaxSys.Click
        Dim iToDelete As Integer = 0

        iToDelete = lboxTaxSys.SelectedIndex
        If (iToDelete = -1) Then
            MessageBox.Show("No entry selected for deletion", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        'if valid line selected, remove the appropriate entries
        iToDelete = CInt(CDbl(iToDelete) / 2.0 - 0.05) 're-scales; uses zero-based index
        citeTaxSys.Remove(iToDelete + 1) 'one-based index for collection
        boolTaxSys.Remove(iToDelete + 1)
        citeTaxSysLWC.Remove(iToDelete + 1)
        sTaxSysMods.RemoveAt(iToDelete) 'zero-based index for stringcollection
        iToDelete = iToDelete * 2 're-expands the index
        lboxTaxSys.Items.RemoveAt(iToDelete) 'removes the citation line
        lboxTaxSys.Items.RemoveAt(iToDelete) 'removes the modifications line
        btnEditTaxSys.Enabled = False : btnDelTaxSys.Enabled = False
    End Sub

    Private Sub lboxTaxSys_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lboxTaxSys.SelectedIndexChanged
        If lboxTaxSys.SelectedItems.Count() > 0 Then btnEditTaxSys.Enabled = True : btnDelTaxSys.Enabled = True Else btnEditTaxSys.Enabled = False : btnDelTaxSys.Enabled = False
    End Sub

    Private Sub btnAddTaxIDRef_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddTaxIDRef.Click
        Dim sTemp As String = ""
        Dim oNewCite As New CiteInfo 'taxonomic system classification system citation
        Dim bNewCiteLWC As Boolean = False
        Dim oNewCiteLWC As New CiteInfo 'taxonomic system classification system larger work citation
        Dim frmAddTaxIDRef As New frmCiteInfo(oNewCite, oNewCiteLWC, bNewCiteLWC, frmMain.getTimeStyle())

        frmAddTaxIDRef.ShowDialog()
        If (frmAddTaxIDRef.getUpdated() = True) Then 'create the new taxonomic system entry
            oNewCite = frmAddTaxIDRef.getNewCite()
            bNewCiteLWC = frmAddTaxIDRef.getLWC()
            oNewCiteLWC = frmAddTaxIDRef.getNewLWC()
            citeTaxIDRef.Add(oNewCite)
            boolTaxIDRef.Add(bNewCiteLWC)
            citeTaxIDRefLWC.Add(oNewCiteLWC)
            sTemp = oNewCite.Author & " — " & oNewCite.Title
            lboxTaxIDRef.Items.Add(sTemp)
        End If

    End Sub

    Private Sub btnEditTaxIDRef_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEditTaxIDRef.Click
        Dim sTemp As String = ""
        Dim iCount As Integer = lboxTaxIDRef.Items.Count
        Dim iToEdit As Integer = lboxTaxIDRef.SelectedIndex
        If (iCount = 1) Then iToEdit = 0
        If (iToEdit = -1) Then
            MessageBox.Show("No entry selected for editing", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        'if valid line selected, set up to edit the appropriate entries
        Dim oNewCite As CiteInfo = CType(citeTaxIDRef(iToEdit + 1), CiteInfo) 'taxonomic system ID reference citation
        Dim bNewCiteLWC As Boolean = CType(boolTaxIDRef(iToEdit + 1), Boolean)
        Dim oNewCiteLWC As CiteInfo = CType(citeTaxIDRefLWC(iToEdit + 1), CiteInfo) 'associated larger work citation

        Dim frmEditTaxIDRef As New frmCiteInfo(oNewCite, oNewCiteLWC, bNewCiteLWC, frmMain.getTimeStyle())
        frmEditTaxIDRef.ShowDialog()
        If (frmEditTaxIDRef.getUpdated() = True) Then 'create the new taxonomic ID reference
            oNewCite = frmEditTaxIDRef.getNewCite()
            bNewCiteLWC = frmEditTaxIDRef.getLWC()
            oNewCiteLWC = frmEditTaxIDRef.getNewLWC()
            citeTaxIDRef.Add(oNewCite, , iToEdit + 1)
            boolTaxIDRef.Add(bNewCiteLWC, , iToEdit + 1)
            citeTaxIDRefLWC.Add(oNewCiteLWC, , iToEdit + 1)
            'delete old taxonomic system entry
            citeTaxIDRef.Remove(iToEdit + 2)
            boolTaxIDRef.Remove(iToEdit + 2)
            citeTaxIDRefLWC.Remove(iToEdit + 2)

            sTemp = oNewCite.Author & " — " & oNewCite.Title
            lboxTaxIDRef.Items.Insert(iToEdit, sTemp)
            lboxTaxIDRef.Items.RemoveAt(iToEdit + 1) 'removes old citation
        End If
        btnEditTaxIDRef.Enabled = False : btnDelTaxIDRef.Enabled = False
    End Sub

    Private Sub btnDelTaxIDRef_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelTaxIDRef.Click
        Dim iToDelete As Integer = 0

        iToDelete = lboxTaxIDRef.SelectedIndex
        If (iToDelete = -1) Then
            MessageBox.Show("No entry selected for deletion", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        'if valid line selected, remove the appropriate entries
        citeTaxIDRef.Remove(iToDelete + 1) 'one-based index for collection
        boolTaxIDRef.Remove(iToDelete + 1)
        citeTaxIDRefLWC.Remove(iToDelete + 1)
        lboxTaxIDRef.Items.RemoveAt(iToDelete) 'removes the citation from the list box
        btnEditTaxIDRef.Enabled = False : btnDelTaxIDRef.Enabled = False
    End Sub

    Private Sub lboxTaxIDRef_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lboxTaxIDRef.SelectedIndexChanged
        If lboxTaxIDRef.SelectedItems.Count() > 0 Then btnEditTaxIDRef.Enabled = True : btnDelTaxIDRef.Enabled = True Else btnEditTaxIDRef.Enabled = False : btnDelTaxIDRef.Enabled = False
    End Sub

    Private Sub btnAddTaxID_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddTaxID.Click
        Dim sTemp As String = ""
        Dim oNewContact As New ContactInfo 'taxonomic system: identifier
        Dim frmAddTaxID As New frmContact(oNewContact, 1)

        frmAddTaxID.ShowDialog()
        If (frmAddTaxID.getUpdated() = True) Then 'create the new taxonomic system: identifier entry
            oNewContact = frmAddTaxID.getConInfo()
            cntTaxID.Add(oNewContact)
            If (oNewContact.PrimaryPerson = True) Then 'update the listbox
                lboxTaxID.Items.Add(oNewContact.Person)
            Else
                lboxTaxID.Items.Add(oNewContact.Organization)
            End If
        End If

    End Sub

    Private Sub btnEditTaxID_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEditTaxID.Click
        Dim iCount As Integer = lboxTaxID.Items.Count
        Dim iToEdit As Integer = lboxTaxID.SelectedIndex
        If (iCount = 1) Then iToEdit = 0
        If (iToEdit = -1) Then
            MessageBox.Show("No entry selected for editing", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        'if valid line selected, set up to edit the appropriate entries
        Dim oFixContact As ContactInfo = CType(cntTaxID(iToEdit + 1), ContactInfo) 'taxonomic system: identifier contact

        Dim frmEditTaxID As New frmContact(oFixContact, 2)
        frmEditTaxID.ShowDialog()
        If (frmEditTaxID.getUpdated() = True) Then 'create the new taxonomic identifier contact
            oFixContact = frmEditTaxID.getConInfo()
            cntTaxID.Add(oFixContact, , iToEdit + 1)
            'delete old taxonomic system identifier entry
            cntTaxID.Remove(iToEdit + 2)

            If (oFixContact.PrimaryPerson = True) Then 'update the listbox
                lboxTaxID.Items.Insert(iToEdit, oFixContact.Person)
            Else
                lboxTaxID.Items.Insert(iToEdit, oFixContact.Organization)
            End If
            lboxTaxID.Items.RemoveAt(iToEdit + 1) 'removes old identier
        End If
        btnEditTaxID.Enabled = False : btnDelTaxID.Enabled = False
    End Sub

    Private Sub btnDelTaxID_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelTaxID.Click
        Dim iToDelete As Integer = 0

        iToDelete = lboxTaxID.SelectedIndex
        If (iToDelete = -1) Then
            MessageBox.Show("No entry selected for deletion", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        'if valid line selected, remove the appropriate entries
        cntTaxID.Remove(iToDelete + 1) 'one-based index for collection
        lboxTaxID.Items.RemoveAt(iToDelete) 'removes the citation from the list box
        btnEditTaxID.Enabled = False : btnDelTaxID.Enabled = False
    End Sub

    Private Sub lboxTaxID_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lboxTaxID.SelectedIndexChanged
        If lboxTaxID.SelectedItems.Count() > 0 Then btnEditTaxID.Enabled = True : btnDelTaxID.Enabled = True Else btnEditTaxID.Enabled = False : btnDelTaxID.Enabled = False
    End Sub

    Private Sub btnAddVoucher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAddVoucher.Click
        Dim sTemp As String = ""
        Dim oNewContact As New ContactInfo 'taxonomic system: voucher repository contact
        Dim sVouchType As String = "" 'taxonomic system: voucher specimen description
        Dim frmAddVoucher As New frmVouchers(sVouchType, oNewContact, 1)

        frmAddVoucher.ShowDialog()
        If (frmAddVoucher.getUpdated() = True) Then 'create the new taxonomic system: voucher
            oNewContact = frmAddVoucher.getVCon()
            sVouchType = frmAddVoucher.getVoucher()
            sVSpecimen.Add(sVouchType)
            cntVouchers.Add(oNewContact)
            sTemp = "specimen: " & Microsoft.VisualBasic.Left(sVouchType, 50)
            lboxVouchers.Items.Add(sTemp)
            If (oNewContact.PrimaryPerson = True) Then
                sTemp = "  repository: " & oNewContact.Person
            Else
                sTemp = "  repository: " & oNewContact.Organization
            End If
            lboxVouchers.Items.Add(sTemp)
        End If

    End Sub

    Private Sub btnEditVoucher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEditVoucher.Click
        Dim iCount As Integer = lboxVouchers.Items.Count
        Dim iToEdit As Integer = lboxVouchers.SelectedIndex
        If (iCount = 1) Then iToEdit = 0
        If (iToEdit = -1) Then
            MessageBox.Show("No entry selected for editing", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        'if valid line selected, remove the appropriate entries
        iToEdit = CInt(CDbl(iToEdit) / 2.0 - 0.05) 're-scales; uses zero-based index
        Dim sTemp As String = ""
        Dim oNewContact As ContactInfo = CType(cntVouchers(iToEdit + 1), ContactInfo) 'taxonomic system: voucher repository contact
        Dim sVouchType As String = sVSpecimen(iToEdit) 'taxonomic system: voucher specimen description
        Dim frmEditVoucher As New frmVouchers(sVouchType, oNewContact, 2)

        frmEditVoucher.ShowDialog()
        If (frmEditVoucher.getUpdated() = True) Then 'update the taxonomic system: voucher
            oNewContact = frmEditVoucher.getVCon()
            sVouchType = frmEditVoucher.getVoucher()
            sVSpecimen.Insert(iToEdit, sVouchType)
            cntVouchers.Add(oNewContact, , iToEdit + 1)

            iToEdit *= 2
            sTemp = "specimen: " & Microsoft.VisualBasic.Left(sVouchType, 50)
            lboxVouchers.Items.Insert(iToEdit, sTemp)
            If (oNewContact.PrimaryPerson = True) Then
                sTemp = "  repository: " & oNewContact.Person
            Else
                sTemp = "  repository: " & oNewContact.Organization
            End If
            lboxVouchers.Items.Insert(iToEdit + 1, sTemp)
            lboxVouchers.Items.RemoveAt(iToEdit + 2) 'removes specimen description
            lboxVouchers.Items.RemoveAt(iToEdit + 2) 'removes repository contact
        End If
        btnEditVoucher.Enabled = False : btnDelVoucher.Enabled = False
    End Sub

    Private Sub btnDelVoucher_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelVoucher.Click
        Dim iToDelete As Integer = 0

        iToDelete = lboxVouchers.SelectedIndex
        If (iToDelete = -1) Then
            MessageBox.Show("No entry selected for deletion", "Selection error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            Return
        End If

        'if valid line selected, remove the appropriate entries
        iToDelete = CInt(CDbl(iToDelete) / 2.0 - 0.05) 're-scales; uses zero-based index
        sVSpecimen.RemoveAt(iToDelete) 'zero-based index for stringcollection
        cntVouchers.Remove(iToDelete + 1) 'one-based index for collection
        iToDelete = iToDelete * 2 're-expands the index
        lboxVouchers.Items.RemoveAt(iToDelete) 'removes the speciment line
        lboxVouchers.Items.RemoveAt(iToDelete) 'removes the contact info line
        btnEditVoucher.Enabled = False : btnDelVoucher.Enabled = False
    End Sub

    Private Sub lboxVouchers_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lboxVouchers.SelectedIndexChanged
        If lboxVouchers.SelectedItems.Count() > 0 Then btnEditVoucher.Enabled = True : btnDelVoucher.Enabled = True Else btnEditVoucher.Enabled = False : btnDelVoucher.Enabled = False
    End Sub

    Private Sub txtTaxCover_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtTaxCover.Leave
        editXMLFile()
    End Sub

    Private Sub txtTaxProc_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtTaxProc.Leave
        editXMLFile()
    End Sub

    Private Sub txtTaxComplete_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtTaxComplete.Leave
        editXMLFile()
    End Sub

    Private Sub frmTabTaxonomy_Leave(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Leave
        editXMLFile()
    End Sub

    Public Sub editXMLFile()
        editNode.Remove("/metadata/idinfo/taxonomy", "keywtax")
        editNode.Remove("/metadata/idinfo/taxonomy/taxonsys", "classsys")
        editNode.Remove("/metadata/idinfo/taxonomy/taxonsys", "idref")
        editNode.Remove("/metadata/idinfo/taxonomy/taxonsys", "ider")
        editNode.Remove("/metadata/idinfo/taxonomy/taxonsys", "taxonpro")
        editNode.Remove("/metadata/idinfo/taxonomy/taxonsys", "taxoncom")
        editNode.Remove("/metadata/idinfo/taxonomy/taxonsys", "vouchers")

        For i As Integer = sTaxKeywords.Count() To 1 Step -1
            Dim newNode As String = ""
            Dim items As String() = sTaxKeywords(i - 1).Split(sPdelim)
            newNode = newNode & "<taxonkt>" & items(0) & "</taxonkt>"
            Dim items2 As String() = items(1).Trim().Split(sKdelim)
            For j As Integer = 0 To items2.GetUpperBound(0)
                newNode = newNode & "<taxonkey>" & items2(j).Trim() & "</taxonkey>"
            Next
            editNode.Add("/metadata/idinfo/taxonomy", "keywtax", "keywtax", newNode)
        Next

        For i As Integer = cntVouchers.Count() To 1 Step -1
            Dim newNodeVoucher As String = ""
            newNodeVoucher = newNodeVoucher & "<specimen>" & sVSpecimen(i - 1) & "</specimen>"
            newNodeVoucher = newNodeVoucher & "<reposit>"
            newNodeVoucher = newNodeVoucher & editNode.createContactInfo(cntVouchers(i))
            newNodeVoucher = newNodeVoucher & "</reposit>"
            editNode.Add("/metadata/idinfo/taxonomy/taxonsys", "vouchers", "vouchers", newNodeVoucher)
        Next

        editNode.Add("/metadata/idinfo/taxonomy/taxonsys", "taxoncom", "taxoncom", txtTaxComplete.Text.Trim())

        editNode.Add("/metadata/idinfo/taxonomy/taxonsys", "taxonpro", "taxonpro", txtTaxProc.Text.Trim())

        For i As Integer = cntTaxID.Count() To 1 Step -1
            Dim newNodeCnt As String = editNode.createContactInfo(cntTaxID(i))
            editNode.Add("/metadata/idinfo/taxonomy/taxonsys", "ider", "ider", newNodeCnt)
        Next

        For i As Integer = citeTaxIDRef.Count() To 1 Step -1
            Dim newNodeRef As String = editNode.createCiteInfo(citeTaxIDRef(i), boolTaxIDRef(i), citeTaxIDRefLWC(i))
            editNode.Add("/metadata/idinfo/taxonomy/taxonsys", "idref", "idref", newNodeRef)
        Next

        For i As Integer = citeTaxSys.Count() To 1 Step -1
            Dim newNodeSys As String = ""
            newNodeSys = newNodeSys & "<classcit>"
            newNodeSys = newNodeSys & editNode.createCiteInfo(citeTaxSys(i), boolTaxSys(i), citeTaxSysLWC(i))
            newNodeSys = newNodeSys & "</classcit>"
            newNodeSys = newNodeSys & "<classmod>" & sTaxSysMods(i - 1) & "</classmod>"
            editNode.Add("/metadata/idinfo/taxonomy/taxonsys", "classsys", "classsys", newNodeSys)
        Next

        editNode.Remove("/metadata/idinfo/taxonomy", "taxoncl")
        Dim newNode2 As String = xmlTaxonClass.InnerXml()
        If newNode2 <> "" Then
            newNode2 = newNode2.Substring(9)
            newNode2 = newNode2.Substring(0, newNode2.Length - 10)
            editNode.Add("/metadata/idinfo/taxonomy", "/taxonsys", "taxoncl", newNode2)
        End If

        editNode.Edit("/metadata/idinfo/taxonomy/taxongen", txtTaxCover.Text.Trim())
    End Sub

    Private Sub button_example_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles button_example.Click
        Dim helpForm As dialog_help = New dialog_help("Taxonomy")
        helpForm.ShowDialog()
    End Sub
End Class